2025-04-27 IPSec zwischen LANCOM-Router und strongSwan auf Alpine Linux

LANCOM 1900EF

IPSec IKEv2 VPN zwischen LANCOM (LCOS) und Alpine Linux mit strongSwan.
Versionen zum Schreibzeitpunkt: LCOS 10.90.0221RU3, Alpine Version 3.21.3, strongswan-5.9.14-r0

In diesem Beispiel hier geht es um ein sogenanntes “RoadWarrior Setup” oder auch einen “Einwahl-Zugang”/RAS. (Mit Linux-Host als Client.) Es soll nicht der ganze Internetverkehr umgeleitet, sondern nur der Zugriff auf ein internes Netz geschaffen werden.

strongSwan

Es passt irgendwie zu IPSec, das nicht nur die dazugehörigen Protokolle, sondern auch die Softwarelandschaft komplex ist. So gibt es mit ⎇strongSwan eine umfangreiche “IPSec-Implementierung” für Linux, die mit mehreren Daemons und inkompatiblen Konfigurationsdateien daher kommt. Sucht man nach Beispielen, wird oft von ipsec.conf geredet und von einem ipsec-Daemon. Hey, das klingt wie die VPN-Technik die man verwenden möchte. Aber Achtung: Die Datei und dazugehörige Syntax ist seit mehreren Jahren abgekündigt/deprecated und soll mit 6.0 komplett verschwinden. Mit ⎇strongswan.conf und ⎇swanctl.conf gibt es eine neue Konfigurationssyntax und mit charon einen ipsec ersetzenden Daemon.
Anderes als ich es von OpenBSD-Projekten gewöhnt bin, wo inkompatible Konfigurationsänderungen - sehr gut erklärt - kurz und schmerzlos durchgedrückt werden, laufen bei strongSwan und den Linux-Distributionen die beiden System seit Jahren parallel. So hatte es z.B. peinlich lange gedauert, bis ich kapiert hatte, das die neue Konfig von einem anderen Daemon verarbeitet werden muss. Das Ding heiß "ipsec" verdamt. Woher kann ich wissen das man da was ganz anderes braucht. ;-)
Wie dem auch sei, diese Anleitung beschreibt nur das “moderne” Vorgehen. (Mal davon ab, dass keine Systemd Distro verwendet wird.)

Authentifizierung mit Pre-Shared Key (PSK)

Auf dem LANCOM ganz normal einen Einwahl-VPN-Zugang anlegen. Der “Fully Qualified Username” muss dem Format einer Email entsprechen und ist dabei das, was später in der swanctl.conf die local- und remote-id sein wird.

Auf Alpine:

# apk add strongswan # vim /etc/swanctl/conf.d/lancom-buero.conf connections { buero { version = 2 proposals = aes256-sha256-ecp512bp encap = yes dpd_delay = 60s remote_addrs = vpn.example.com vips = 0.0.0.0 children { buero { esp_proposals = aes256-sha256-ecp512bp start_action = start dpd_action = restart close_action = start updown = doas /usr/lib/strongswan/_updown iptables remote_ts = 198.51.100.0/24 #mobike = no # bei LCOS <10.90 Systemen auskommentieren } } local { auth = psk id = sw@example } remote { auth = psk id = sw@example } } } secrets { ike-sw { id = sw@example secret = "Passwort" } } #eof # chmod 600 /etc/swanctl/conf.d/lancom-buero.conf Komplett optional, für weniger Meldungen im Syslog. # vim /etc/strongswan.d/lancom-logging.conf charon { syslog { identifier = charon daemon { enc = -1 net = -1 } } } #eof Falls Firewall im Einsatz: # vim /etc/doas.d/charon.conf # IPSec deamon charon permit nopass keepenv ipsec as root cmd /usr/lib/strongswan/_updown args iptables #eof VPN-Verbindung starten: # rc-service charon start Automatisch beim booten starten: # rc-update add charon

“encap = yes” Ohne verarbeitet Linux eingehende, in UDP gekapselte, ESP-Pakete nicht. ¯\_(ツ)_/¯

“remote_addrs = vpn.example.com” Domain des LANCOM-Routers. Trotz AAAA-Record wird sich mit IPv4 verbunden. Grund hab ich bisher nicht weiter analysiert. Evtl. folgt dazu später ein Update.

“remote_ts = 198.51.100.0/24” Das entfernte Netzwerk, in das man will.

“vips = 0.0.0.0” Der Client erhält eine IP vom VPN-Router zugewiesen.

“secret = "Passwort"” Das Shared Secret, der Preshared Key. Wenn die Zeichenkette ein Anführungszeichen enthält, muss diese Base64 kodiert werden. (Zusammen mit einer 0s ⎇Makierung). Dazu dieser Einzeiler:
SWB64P=`mktemp` && base64 > $SWB64P && echo && echo 0s`cat $SWB64P` && rm $SWB64P
Wichtig: Nach der Passworteingabe nicht Enter drücken, sondern dreimal Strg + d. Andernfalls wird der Zeilenumbruch mitkodiert und die Authentifizierung wird scheitern. Der Einzeiler ist nur auf Busybox getestet.

Authentifizierung mit Zertifikat

Wie man eine CA erstellt und den LANCOM-Router dafür konfiguriert, habe ich in meinem OpenSSL-Spickzettel beschrieben:
⍈openssl.txt
⍈openssl_Beispiel.cnf
Einfach dem Beispiel "Android mit strongSwan" folgen. Der Weg ist mehr oder weniger der Gleiche.

Auf Alpine:
Mit Cert- und Key-File:

# cp ORGANIZATION_CACert.pem /etc/swanctl/x509ca/ # cp ClientXYZ-FQDN_Cert.pem /etc/swanctl/x509/ # cp ClientXYZ-FQDN_Key.pem /etc/swanctl/private/ # chmod 400 /etc/swanctl/private/ClientXYZ-FQDN_Key.pem # vim /etc/swanctl/conf.d/lancom-buero.conf connections { buero { version = 2 proposals = aes256-sha256-ecp512bp encap = yes dpd_delay = 60s remote_addrs = vpn.example.com vips = 0.0.0.0 children { buero { esp_proposals = aes256-sha256-ecp512bp start_action = start dpd_action = restart close_action = start updown = doas /usr/lib/strongswan/_updown iptables remote_ts = 198.51.100.0/24 #mobike = no # bei LCOS <10.90 Systemen auskommentieren } } local { auth = pubkey certs = ClientXYZ-FQDN_Cert.pem } remote { cacerts = ORGANIZATION_CACert.pem } } } #eof


Mit PKCS #12 Zertifikatcontainer:

# cp ORGANIZATION_CACert.pem /etc/swanctl/x509ca/ # cp ClientXYZ-FQDN_Cert_with_Key.p12 /etc/swanctl/pkcs12/ # openssl x509 -subject -noout -in ClientXYZ-FQDN_Cert_with_Key.p12 subject=C=DE, ST=Bavaria, O=example.com, OU=Example.com Certification Authority, CN=vpn.example.com, emailAddress=camaster@example.com # vim /etc/swanctl/conf.d/lancom-buero.conf ... local { auth = pubkey id = C=DE, ST=Bavaria, O=example.com, OU=Example.com Certification Authority, CN=vpn.example.com, emailAddress=camaster@example.com } remote { cacerts = ORGANIZATION_CACert.pem } } } secrets { pkcs12 { file = ClientXYZ-FQDN_Cert_with_Key.p12 secret = "Passwort" } } #eof # chmod 400 /etc/swanctl/conf.d/lancom-buero.conf

Der secrets-Abschnitt ist optional. Ohne wird beim Starten des Daemon nach dem Passwort der p12-Datei gefragt.

Wie üblich die Erinnerung das einzelne VPN-Verbindung von LCOS als eigene Gegenstellen betrachtet werden und evtl. in der Firewall weitere Freigaben für die Kommunikation untereinander benötigt werden.

⍈Homepage

#